package org.carabiner.infinitest.swingui;

import java.awt.Color;

import org.carabiner.infinitest.InfinitestSettings;

class ColorAnimator
{
  private static final int SECOND = 1000;
  private static final int MINUTE = SECOND * 60;
  private int angerLevel;
  private int animationCounter;
  private int animationStep = 1;
  private static final int[] ANGER_LEVEL_TIME_CUTOFFS = new int[]{MINUTE, MINUTE * 2, MINUTE * 3, MINUTE * 5, MINUTE * 8, MINUTE * 13, MINUTE * 21, MINUTE * 34, MINUTE * 55, MINUTE * 89};

  int getAngerLevel()
  {
    return angerLevel;
  }

  void setAngerLevel(int level)
  {
    if (level > getMaxAngerLevel())
      throw new IllegalArgumentException("Level must be less than or equal to 10, was " + level);
    if (level < 0)
      throw new IllegalArgumentException("Level must be greater than zero, was " + level);
    angerLevel = level;
    updateStep();
  }

  static int getMaxAngerLevel()
  {
    return ANGER_LEVEL_TIME_CUTOFFS.length;
  }

  public Color shiftColorOnAnimationTick(Color color)
  {
    if (!color.equals(InfinitestSettings.FAILURE_COLOR))
      return color;
    double shift = getColorShiftForAnimationTick();
    if (shift < 0)
      throw new IllegalStateException("Shift cannot be less than zero! " + getAnimationLength() + " " + getAngerLevel() + " " + animationCounter);
    return new Color((int)(color.getRed() * shift), (int)(color.getGreen() * shift), (int)(color.getBlue() * shift));
  }
  
  double getColorShiftForAnimationTick()
  {
    double maxDelta = getAngerLevel() * 0.1d;
    double delta = maxDelta * ((double)animationCounter / (double)getAnimationLength() );
    return 1.0d - delta;
  }

  private int getAnimationLength()
  {
    return (getMaxAngerLevel() + 1) - getAngerLevel();
  }

  public int getAnimationRate()
  {
    return 100;
  }

  public void tick()
  {
    animationCounter += animationStep;
    updateStep();
  }

  private void updateStep()
  {
    if (animationCounter >= getAnimationLength())
    {
      animationStep = -1;
      animationCounter = getAnimationLength();
    }
    if (animationCounter == 0 )
    {
      animationStep = 1;
    }
  }

  public void setAngerBasedOnTime(long timeSinceGreen)
  {
    int angerLevel = 0;
    while (angerLevel < ANGER_LEVEL_TIME_CUTOFFS.length && timeSinceGreen >= ANGER_LEVEL_TIME_CUTOFFS[angerLevel])
      angerLevel++;
    setAngerLevel(angerLevel);
  }

}
